import { Injectable } from '@nestjs/common';
import { Interval } from '@nestjs/schedule';
import { AwardService } from 'src/award/award.service';
import { clockModel } from 'src/clock/entities/clock.entity';
import { WxService } from 'src/wx/wx.service';
import {
  NotifyQueueItem,
  notifyQueueModel,
} from './entities/notifyQueue.entity';

@Injectable()
export class NotifyService {
  @Interval(1000)
  async triggerNotifications() {
    const notifyqueue: NotifyQueueItem[] = await notifyQueueModel.findAll();
    notifyqueue.forEach(async (notify) => {
      const procession = Date.now() - notify.start_timestamp;
      if (procession >= notify.target_timestamp) {
        // 由于用户可能在运行中更改任务名称，所以不使用name检索
        await this.notifyUser(
          notify.openid,
          notify.id,
          notify.start_timestamp,
          notify.target_timestamp,
          notify.name,
          notify.tags,
        );
      }
    });
  }

  /**
   *
   * @description 当执行该函数时，表明计时完毕。并向用户推送计时结束消息
   */
  async notifyUser(
    openid: string,
    id: string,
    start_timestamp: number,
    target_timestamp: number,
    name: string,
    tags: Array<string>,
  ) {
    // 先将clockItem中的运行状态变为false
    await clockModel.updateOne(
      { openid, 'clocks.id': id },
      { $set: { 'clocks.$.playing': false, 'clocks.$.now_timestamp': 0 } },
    );
    // 从定时队列中删除
    await this.deleteItem(openid, id);
    const awardService = new AwardService();
    // 到这里表示一个番茄钟任务彻底完成，需要发放奖励了
    const awardId = await awardService.finishedAward(openid, name, tags);
    // 通过调用微信接口，发送通知消息给用户
    const wxService = new WxService();
    const duration = `${target_timestamp / 60000}分钟`;
    // const clock = new ClockService();
    // const clockItem = await clock.findItem(openid, id);

    const result = await wxService.subscribeMessage(
      openid,
      awardId,
      name,
      start_timestamp,
      duration,
    );
    if (!result) {
      console.log('微信消息通知失败');
    }
  }

  async findOne(openid: string, id: string) {
    const notify = await notifyQueueModel.findOne<NotifyQueueItem>({
      openid,
      id,
    });
    return notify;
  }

  async addItem(
    openid: string,
    id: string,
    target_timestamp: number,
    name: string,
    tags: Array<string>,
  ) {
    const notify = await this.findOne(openid, id);
    if (notify) {
      return false;
    } else {
      notifyQueueModel.insertOne({
        openid,
        id,
        target_timestamp,
        start_timestamp: Date.now(),
        name,
        tags,
      });
      return true;
    }
  }

  async deleteItem(openid: string, id: string) {
    const result = await notifyQueueModel.findOneAndDelete<NotifyQueueItem>({
      openid,
      id,
    });
    return result.value;
  }
}
